package stream;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamDemo8 {
    /* 分组(partitioningBy/groupingBy)
        分区：将stream按条件分为两个Map，比如员工按薪资是否高于8000分为两部分。
        分组：将集合分为多个Map，比如员工按性别分组。有单级分组和多级分组
     */
    public static void main1(String[] args) {
        List<Student> list = Arrays.asList(
                new Student("张三", 20, 9999, "上海"),
                new Student("李四", 20, 8888, "北京"),
                new Student("王五", 28, 7777, "广州"),
                new Student("赵六", 28, 6666, "深圳"),
                new Student("田七", 28, 5555, "杭州")
        );
        //1.将员工按薪资是否高于8000分组
        // 会分成两组，true表示薪资高于8000，false表示低于8000
        Map<Boolean, List<Student>> collect = list.stream().collect(Collectors.partitioningBy(s -> s.getSalary() > 8000));
        System.out.println(collect);
        System.out.println("--------------------------------");
        //2.将员工先按薪资分组,再按地区分组 可以嵌套分组，比如员工按性别分组，再按地区分组
        Map<Integer, Map<String, List<Student>>> collect1 = list.stream().collect(Collectors.groupingBy(Student::getSalary, Collectors.groupingBy(Student::getAddress)));
        collect1.forEach((k,y) -> System.out.println(k + "=" + y));
    }
// 接合(joining)
//
//joining可以将stream中的元素用特定的连接符（没有的话，则直接连接）连接成一个字符串。
    public static void main2(String[] args) {
        List<Student> list = Arrays.asList(
                new Student("张三", 20, 9999, "上海"),
                new Student("李四", 20, 8888, "北京"),
                new Student("王五", 28, 7777, "广州"),
                new Student("赵六", 28, 6666, "深圳"),
                new Student("田七", 28, 5555, "杭州")
        );
        //1. 将所有Student的姓名连接成一个字符串,姓名之间使用"-"分隔
        String collect = list.stream().map(Student::getName).collect(Collectors.joining("-"));
        System.out.println(collect);
        System.out.println("--------------------------------");
        //2.将集合中的元素连接成一个字符串，元素之间使用"-"分隔
        List<String> list1 = Arrays.asList("aa", "bb", "cc");
        String collect1 = list1.stream().collect(Collectors.joining("--"));
        System.out.println(collect1);
    }
// 排序(sorted)
//
//sorted，中间操作。有两种排序：
//
//1. sorted()：自然排序，流中元素需实现Comparable接口
//2. sorted(Comparator com)：Comparator排序器自定义排序
    public static void main3(String[] args) {
        List<Student> list = Arrays.asList(
                new Student("张三", 20, 9999, "上海"),
                new Student("李四", 20, 8888, "北京"),
                new Student("王五", 28, 7777, "广州"),
                new Student("赵六", 28, 6666, "深圳"),
                new Student("田七", 28, 5555, "杭州")
        );
        // // 1. 将员工按工资由高到低排序
        List<Student> collect = list.stream().sorted(Comparator.comparing(Student::getSalary).reversed()).collect(Collectors.toList());
        collect.forEach(item -> System.out.println(item));
        System.out.println("------------------------------------------");

        //2. 将员工先按工资由低到高排序，再按照年龄由高到低
        List<Student> collect1 = list.stream().sorted((a, b) -> {
            if (a.getSalary() == b.getSalary()) {
                return b.getAge() - a.getAge();
            } else {
                return a.getSalary() - b.getSalary();
            }
        }).collect(Collectors.toList());
        collect1.forEach(item -> System.out.println(item));

    }

    //提取/组合
    //
    //流也可以进行合并、去重、限制、跳过等操作。
    //组合：concat , 将两个流进行合并
    //去重： distinct ，去除重复数据
    //跳过：skip ，跳过元素，返回一个扔掉前n个元素的流，若流中元素不足n个，则返回一个空流，与limit(n)互补
    //限制：limit ，截断流，返回一个截断后的流，与skip(n)互补
    public static void main(String[] args) {
        // 1. 准备两个数组
        String[] arr1 = {"a", "b", "c"};
        String[] arr2 = {"a", "d", "c", "e", "f"};

        // 2. 准备两个流
        Stream<String> stream = Arrays.stream(arr1);
        Stream<String> stream1 = Arrays.stream(arr2);

        //3. 合并两个流 并去重
        List<String> collect = Stream.concat(stream, stream1).distinct().collect(Collectors.toList());
        collect.forEach(System.out::print);

        //4.限制：limit，跳过：skip
        collect.stream().skip(2).limit(2).forEach(System.out::print);
    }
}
